/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */

/*
 * @Author: xvrui && 3505897045@qq.com
 * @Date: 2024-07-01 17:17:38
 * @LastEditors: RayX 3505897045@qq.com
 * @LastEditTime: 2024-07-06 10:46:44
 * @FilePath: /ns-3.26/src/ipsecinhitipv4/helper/ipsecinhitipv4-helper.cc
 * @Description: 
 * 
 */
#include "../model/ipsecinhitipv4.h"
#include "ipsecinhitipv4-helper.h"
#include "ns3/network-module.h"
#include "ns3/core-module.h"
#include "ns3/internet-stack-helper.h"
#include "ns3/ipv4-l3-protocol.h"
#include "ns3/ipv6-l3-protocol.h"
#include "ns3/log.h"
#include "ns3/internet-module.h"

using namespace ns3;
namespace ns3{

    NS_LOG_COMPONENT_DEFINE("ipsechelper");

    IpSecInhitIpv4Helper::IpSecInhitIpv4Helper(){}
    IpSecInhitIpv4Helper::~IpSecInhitIpv4Helper(){}

    void IpSecInhitIpv4Helper::InstallIpSec(NodeContainer &nodes) const{
        InternetStackHelper internetHelper;
        internetHelper.Install(nodes);


        for (NodeContainer::Iterator n = nodes.Begin(); n != nodes.End(); n++){
            Ptr<Node> node= *n;
            // remove ipv4l3protocol
            Ptr<Ipv4L3Protocol> ipv4 = node->GetObject<Ipv4L3Protocol>();
            // add ipsec
            Ptr<IpSecInhitIpv4> ipsec = CreateObject<IpSecInhitIpv4> ();
            node->AggregateObject(ipsec);

        }
    }

    void IpSecInhitIpv4Helper::Install(NodeContainer &nodes) const{
        for(NodeContainer::Iterator it=nodes.Begin();it!=nodes.End();it++){
            Install(*it);
        }
    }
    void IpSecInhitIpv4Helper::Install(Ptr<Node> node) const
    {
        NS_LOG_FUNCTION(this);
        // CreateAndAggregateObjectFromTypeId(node, "ns3::IpSecInhitIpv4");
        // CreateAndAggregateObjectFromTypeId (node, "ns3::ArpL3Protocol");
        // // CreateAndAggregateObjectFromTypeId (node, "ns3::Ipv4L3Protocol");
        // CreateAndAggregateObjectFromTypeId (node, "ns3::Icmpv4L4Protocol");

        // CreateAndAggregateObjectFromTypeId (node, "ns3::TrafficControlLayer");
        // CreateAndAggregateObjectFromTypeId (node, "ns3::UdpL4Protocol");
        // // // Set routing
        // Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
        // Ptr<Ipv4RoutingProtocol> ipv4Routing = m_routing->Create(node);
        // ipv4->SetRoutingProtocol(ipv4Routing);

        if (node->GetObject<Ipv4>() != 0)
        {
            NS_FATAL_ERROR("InternetStackHelper::Install (): Aggregating "
                           "an InternetStack to a node with an existing Ipv4 object");
            return;
        }

        CreateAndAggregateObjectFromTypeId(node, "ns3::ArpL3Protocol");
        // CreateAndAggregateObjectFromTypeId(node, "ns3::Ipv4L3Protocol");
        CreateAndAggregateObjectFromTypeId (node,"ns3::IpSecInhitIpv4");
        CreateAndAggregateObjectFromTypeId(node, "ns3::Icmpv4L4Protocol");

        // if (m_ipv4ArpJitterEnabled == false)
        // {
            Ptr<ArpL3Protocol> arp = node->GetObject<ArpL3Protocol>();
            NS_ASSERT(arp);
            arp->SetAttribute("RequestJitter", StringValue("ns3::ConstantRandomVariable[Constant=0.0]"));
        // }
        // Set routing
        Ptr<Ipv4> ipv4 = node->GetObject<Ipv4>();
        Ipv4RoutingHelper *m_routing;
        Ptr<Ipv4RoutingProtocol> ipv4Routing = m_routing->Create(node);
        ipv4->SetRoutingProtocol(ipv4Routing);

        CreateAndAggregateObjectFromTypeId(node, "ns3::TrafficControlLayer");
        CreateAndAggregateObjectFromTypeId(node, "ns3::UdpL4Protocol");
        ObjectFactory m_tcpFactory;
        node->AggregateObject(m_tcpFactory.Create<Object>());
        Ptr<PacketSocketFactory> factory = CreateObject<PacketSocketFactory>();
        node->AggregateObject(factory);
    }
    void IpSecInhitIpv4Helper::CreateAndAggregateObjectFromTypeId(Ptr<Node> node, const std::string typeId) const {
        ObjectFactory factory;
        factory.SetTypeId(typeId);
        Ptr<Object> protocol = factory.Create<Object>();
        node->AggregateObject(protocol);
    }

}
